// Created by Windward Studios - no copyright is claimed. This code can be used in
// any manner by anyone for any reason. There is no copyright of any kind on it. You may
// use it in commercial products. You may change it without sharing those changes.
// We ask that you keep the "created by Windward Studios" in a comment at the top.

using System.Collections;
using System.Data;
using System.Data.Common;
using Kailua.net.windward.utils;

namespace net.windward.utils.ado.Unknown
{
	///<summary>
	/// Create a WrVendor object for a DB vendor we don't recognize.
	///</summary>
	public class WrUnknownVendor : WrVendor
	{
		/// <summary>
		/// Creates an unknown vendor object.
		/// </summary>
		/// <param name="name">The friendly name of the provider.</param>
		/// <param name="description">The description of this provider (optional).</param>
		/// <param name="providerClass">The class of the provider.</param>
		public WrUnknownVendor(string name, string description, string providerClass)
			: base(name, description, providerClass)
		{
		}

		/// <summary>
		/// True if can enumerate running servers from this vendor. This is implemented seperately from
		/// CanCreateDataSourceEnumerator because DB2 and SqlServer implement CreateDataSourceEnumerator differently.
		/// </summary>
		public override bool CanEnumerateServers
		{
			get
			{
				if (providerFactory == null)
					return false;
				return providerFactory.CanCreateDataSourceEnumerator;
			}
		}

		/// <summary>
		/// True if can launch the administrator for this vendor. This will return true if it can find the admin
		/// program file. In that case the launch could still fail.
		/// </summary>
		public override bool CanLaunchAdministrator
		{
			get { return false; }
		}

		/// <summary>
		/// True if can run DDL scripts.
		/// </summary>
		public override bool CanRunScripts
		{
			get { return false; }
		}

		/// <summary>
		/// True if can use the WindowsIdentity of the caller eliminating the need to pass a username and password.
		/// </summary>
		public override bool CanUseTrustedConnection
		{
			get { return false; }
		}

		/// <summary>
		/// True if this vendor has the concept of databases in an installed copy of their product. This is false for Oracle (which
		/// does not have the concept of a database) and for databases like Access that are just a file - and the file is the "server."
		/// </summary>
		public override DATABASE_MODE DatabaseMode
		{
			get { return DATABASE_MODE.OPTIONAL; }
		}

		/// <summary>
		/// All servers from this vendor on the network. This may not get all due to routers not passing
		/// on a broadcast or delays in some servers responding.
		/// </summary>
		/// <exception cref="WrDbException">Thrown if this provider does not support enumerate servers.</exception>
		/// <returns>All servers found on the sub-net.</returns>
		public override IWrServer[] GetServers()
		{
			ArrayList rtn = new ArrayList();
			DbDataSourceEnumerator dsEnum = providerFactory.CreateDataSourceEnumerator();
			if (dsEnum != null)
			{
				DataTable servers = dsEnum.GetDataSources();
				int ordServer = servers.Columns.IndexOf("ServerName");
				int ordInstance = servers.Columns.IndexOf("InstanceName");
				Trap.trap(servers.Rows.Count > 0);
				foreach (DataRow row in servers.Rows)
				{
					string server = (string)row[ordServer];
					string instance = (ordInstance == -1) || row.IsNull(ordInstance) ? null : (string)row[ordInstance];
					if (!string.IsNullOrEmpty(instance))
						server += "\\" + instance;
					rtn.Add(new WrUnknownServer(providerFactory, server));
				}
			}

			rtn.Sort();
			return (WrUnknownServer[])rtn.ToArray(typeof(WrUnknownServer));
		}

		/// <summary>
		/// A connection string for a database on a server.
		/// </summary>
		/// <param name="server">The server to access (ex: localhost).</param>
		/// <param name="database">The database to connect to.</param>
		/// <param name="credentials">The user credentials to access the database.</param>
		/// <param name="showPassword">True to include the password, false to add the password as *****.</param>
		/// <returns>The connection string for this database on this server.</returns>
		public override string ConnectionString(string server, string database, WrCredentials credentials, bool showPassword)
		{
			return ConnectionString(providerFactory, server, database, credentials, showPassword);
		}

		internal static string ConnectionString(DbProviderFactory provider, string server, string database, WrCredentials credentials, bool showPassword)
		{

			if (provider == null)
				return string.Empty;

			// this is an attempt - using SqlServer keys as that is what MS shows and so it's our best bet.
			DbConnectionStringBuilder bldr = provider.CreateConnectionStringBuilder();
			if (!string.IsNullOrEmpty(server))
				bldr["server"] = server;
			if (!string.IsNullOrEmpty(database))
				bldr["database"] = database;
			if (! credentials.UseWindowsIdentity)
			{
				if (!string.IsNullOrEmpty(credentials.Username))
					bldr["Uid"] = credentials.Username;
				if (!string.IsNullOrEmpty(credentials.Password))
					bldr["Pwd"] = showPassword ? credentials.Password : "*****";
			}

			return bldr.ConnectionString;
		}

		/// <summary>
		/// Returns a new instance of the provider's class that implements the WrCommand class.
		/// </summary>
		/// <returns>A new instance of WrCommand.</returns>
		public override WrCommand CreateCommand()
		{
			return new WrUnknownCommand(providerFactory);
		}

		/// <summary>
		/// Create a server object.
		/// </summary>
		/// <param name="server">The name of the server the database is on.</param>
		public override IWrServer CreateServer(string server)
		{
			return new WrUnknownServer(providerFactory, server);
		}

	}
}
